package top.hmtools.manager;

import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import top.hmtools.RLContext;
import top.hmtools.base.StringTools;
import top.hmtools.pojo.RequestLogBean;

/**
 * 缺省的日志记录管理者（支持同步、异步写入日志信息到数据库）
 * @author Jianghaibo
 *
 */
public class RequestLoggerManagerDefault implements IRequestLoggerManager {
    
    private static Logger logger = LoggerFactory.getLogger(RequestLoggerManagerDefault.class);
    
    @Autowired
    private RLContext rlContext;
    
    /**
     * 方法说明
     * 输入参数说明
     * 输出参数说明
     */
    @Override
    public void init() {
        //skip
    }

    /**
     * 方法说明
     * 输入参数说明
     * 输出参数说明
     */
    @Override
    public void destroy() {
        logger.debug("销毁开始。。。缓存中的日志记录未写入数据库总记录数："+this.rlContext.requestLogBeanQueue.getQueueSize());
        List<RequestLogBean> logBeans = new ArrayList<RequestLogBean>();
        while(this.rlContext.requestLogBeanQueue.getQueueSize()>0){
            //从队列中取出指定单批次数据条数的日志记录，并拼接成list集合
            for(int ii=0;ii<this.rlContext.requestLoggerAutoConfiguration.getBatchItemSize();ii++){
                RequestLogBean logBean = this.rlContext.requestLogBeanQueue.poll();
                if(logBean==null || StringTools.isBlank(logBean.getRequestID())){
                	continue;
                }
                logBeans.add(logBean);
            }
            try {
            	//批量写入数据库
            	int addedLogsCounts = this.rlContext.requestLoggerService.addLogs(logBeans);
            	logger.debug("成功写入数据库日志记录数为："+addedLogsCounts);
            	logBeans.clear();
			} catch (Exception e) {
				e.printStackTrace();
				logger.error("写入数据库的追加扩展日志失败："+e.getMessage(),e);
				logger.error("尝试补救，一条一条写入数据库。。。");
				int count = 0;
				for(RequestLogBean bean:logBeans){
					try {
						count = count + this.rlContext.requestLoggerService.addLogs(bean);
					} catch (Exception e2) {
						logger.error("无法写入到数据库的数据：");
						logger.error(bean.toString());
					}
				}
				logger.error("成功补救"+count+"条。。。");
			}
        }
        
        logger.debug("缓存中的追加的日志扩展记录未写入数据总记录数："+this.rlContext.requestLogBeanExtraQueue.getQueueSize());
        while(this.rlContext.requestLogBeanExtraQueue.getQueueSize()>0){
        	//从队列中取出指定单批次数据条数的日志记录，并拼接成list集合
        	for(int ii=0;ii<this.rlContext.requestLoggerAutoConfiguration.getBatchItemSize();ii++){
        		RequestLogBean requestLogBeanExtra = this.rlContext.requestLogBeanExtraQueue.poll();
        		if(requestLogBeanExtra == null || StringTools.isBlank(requestLogBeanExtra.getRequestID())){
        			continue;
        		}
        		logBeans.add(requestLogBeanExtra);
        	}
        	
        	try {
        		int addLogsExtraInfos = this.rlContext.requestLoggerService.addLogsExtraInfos(logBeans);
        		logger.debug("成功写入数据库的追加扩展日志记录数为："+addLogsExtraInfos);
        		logBeans.clear();
			} catch (Exception e) {
				e.printStackTrace();
				logger.error("写入数据库的追加扩展日志失败："+e.getMessage(),e);
				logger.error("尝试补救，一条一条写入数据库。。。");
				int count = 0;
				for(RequestLogBean bean:logBeans){
					try {
						count = count + this.rlContext.requestLoggerService.addLogsExtraInfos(bean);
					} catch (Exception e2) {
						logger.error("无法写入到数据库的数据：");
						logger.error(bean.toString());
					}
				}
				logger.error("成功补救"+count+"条。。。");
			}
        }
        logger.debug("销毁结束。。。");
    }

    /**
     * 方法说明
     * 输入参数说明
     * 输出参数说明
     */
    @Override
    public boolean addRequestLoggerBeanToQueue(RequestLogBean requestLogBean) {
        //将日志信息加入缓存队列
        boolean result = this.rlContext.requestLogBeanQueue.add(requestLogBean);
        int batchItemSize = this.rlContext.requestLoggerAutoConfiguration.getBatchItemSize();
        
        //同步方式写入数据库，检查缓存队列中的总条数是否达到批次写入数据库的单批次数据条数。
        if(this.rlContext.requestLogBeanQueue.getQueueSize()>=batchItemSize){
            List<RequestLogBean> logBeans = new ArrayList<RequestLogBean>();
            //从队列中取出指定单批次数据条数的日志记录，并拼接成list集合
            for(int ii=0;ii<batchItemSize;ii++){
                RequestLogBean logBean = this.rlContext.requestLogBeanQueue.poll();
                if(logBean==null || StringTools.isBlank(logBean.getRequestID())){
                    continue;
                }
                logBeans.add(logBean);
            }
            
            try {
            	//批量写入数据库
            	this.rlContext.requestLoggerService.addLogs(logBeans);
			} catch (Exception e) {
				e.printStackTrace();
				logger.error("同步方式批量写日志信息到数据库发生错误。。。"+e.getMessage(),e);
				logger.error("尝试补救，一条一条写入数据库。。。");
				int count = 0 ;
				for(RequestLogBean bean : logBeans){
					try {
						count = count + this.rlContext.requestLoggerService.addLogs(bean);
					} catch (Exception e2) {
						logger.error("无法写入到数据库的数据：");
						logger.error(bean.toString());
					}
				}
				logger.error("成功补救"+count+"条。。。");
			}
        }
        return result;
    }

	@Override
	public boolean addRequestLoggerBeanExtraToQueue(RequestLogBean requestLogBeanExtra) {
		boolean result = this.rlContext.requestLogBeanExtraQueue.add(requestLogBeanExtra);//将数据写入队列
		int batchItemSize = this.rlContext.requestLoggerAutoConfiguration.getBatchItemSize();
		
		//同步方式写入数据库，检查缓存队列中的总条数是否达到批次写入数据库的单批次数据条数。
		if(this.rlContext.requestLogBeanExtraQueue.getQueueSize() >= batchItemSize){
			List<RequestLogBean> logBeans = new ArrayList<RequestLogBean>();
            //从队列中取出指定单批次数据条数的日志记录，并拼接成list集合
            for(int ii=0;ii<batchItemSize;ii++){
            	RequestLogBean logBeanExtra = this.rlContext.requestLogBeanExtraQueue.poll();
            	if(logBeanExtra == null || StringTools.isBlank(logBeanExtra.getRequestID())){
            		continue;
            	}
            	logBeans.add(logBeanExtra);
            }
            
            try {
				//批量写入数据库
            	this.rlContext.requestLoggerService.addLogsExtraInfos(logBeans);
			} catch (Exception e) {
				e.printStackTrace();
				logger.error("同步方式批量写追加的日志扩展信息到数据库发生错误。。。"+e.getMessage(),e);
				logger.error("尝试补救，一条一条写入数据库。。。");
				int count = 0 ;
				for(RequestLogBean bean : logBeans){
					try {
						count = count + this.rlContext.requestLoggerService.addLogsExtraInfos(bean);
					} catch (Exception e2) {
						logger.error("无法写入到数据库的数据：");
						logger.error(bean.toString());
					}
				}
				logger.error("成功补救"+count+"条。。。");
			}
		}
		return result;
	}

}
